﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using BoYuanCore.Framework.Extensions;
using KeXin.Model.Output;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Serilog;

namespace KeXinApi.Code
{
    /// <summary>
    /// 全局异常拦截中间件
    /// </summary>
    public static class GlobalExceptionConfiguration
    {
        public static void ConfigureExceptionHandler(this IApplicationBuilder app)
        {
            app.UseExceptionHandler(e =>
            {
                e.Run(async context =>
                {
                    // 捕获请求 JSON
                    var stream = context.Request.Body;
                    context.Request.EnableBuffering();
                    if (stream.CanSeek)
                        stream.Seek(0, SeekOrigin.Begin);

                    string jsonStr = await new StreamReader(stream, Encoding.UTF8).ReadToEndAsync();
                    var url = context.Request.GetEncodedUrl();
                    StringBuilder sb = new StringBuilder();

                    sb.AppendLine("");
                    sb.AppendLine("========请求json开始========");
                    sb.AppendLine("url: " + url);
                    sb.AppendLine(jsonStr);
                    sb.AppendLine("========请求json结束========");

                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;//http 500错误码
                    context.Response.ContentType = "application/json";

                    var feature = context.Features.Get<IExceptionHandlerPathFeature>();
                    var exception = feature.Error;
                    string num = Guid.NewGuid().ToString("N");
                    Log.Error(exception.GetExceptionMsg("异常编号:" + num + sb.ToString()));

                    var result = ResponseOutput.NotOk<string>("服务器异常,异常编号:" + num, code: context.Response.StatusCode);

                    JsonSerializerSettings setting = new JsonSerializerSettings
                    {
                        // 设置为驼峰命名
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    };
                    await context.Response.WriteAsync(JsonConvert.SerializeObject(result, setting));

                });
            });
        }
    }
}
/*UseExceptionHandler与IExceptionFilter 区别:拦截范围的不同。
 IExceptionFilter 只拦截action层面的异常。如果是控制器内部发生了异常，首先是由过滤器捕获到异常，最后才是中间件捕获到异常。
参考:https://www.cnblogs.com/dotnet261010/p/13193124.html 
*/
/*

  //允许body重复读取(异常时获取请求json)
  app.Use(next => context =>
            {
                context.Request.EnableBuffering();
                return next(context);
            });

 //调用方法
 app.ConfigureExceptionHandler();//全局异常中间件 
 */